package uni.androidgame.mapgeneration;

import android.graphics.Canvas;
import android.util.Log;

import java.util.ArrayList;
import java.util.LinkedList;

import uni.androidgame.gameobjects.DungeonMap;
import uni.androidgame.gameobjects.Monster;

public class MapGenerator
{
    public static final int minWidth = 6;
    public static final int minHeight = 6;
    private static DungeonMap rootNode;
    public static int getRandom(int min, int max) {
        return min + (int)(Math.random() * ((max - min) + 1));
    }
    public static int getRandom(float min, float max) {
        return (int)(min + (Math.random() * ((max - min) + 1)));
    }


    public static DungeonMap generateMap(int width, int height)
    {

        rootNode = new DungeonMap(width,height);

        //Creates the BSP tree and saves the leaf nodes
        ArrayList<BSPMapNode> leaves = createBSPAndGetLeaves(rootNode);

        //Uses the leaves to create rooms and saving the unique parents of the leaves
        LinkedList<BSPMapNode> parentsOfLeaves = createRoomsAndGetParents(leaves);

        //The parents are used to connect the subregions by bottom up traversel
        connectRooms(parentsOfLeaves);

        Log.w("MapGen","Created "+leaves.size()+" rooms");


        return rootNode;
    }

    private static ArrayList<BSPMapNode> createBSPAndGetLeaves(BSPMapNode root)
    {

        ArrayList<BSPMapNode> nodesLeft= new ArrayList<BSPMapNode>();
        ArrayList<BSPMapNode> leaves = new ArrayList<BSPMapNode>();
        BSPMapNode currentNode;

        nodesLeft.add(root);

        while(!nodesLeft.isEmpty())
        {
            currentNode = nodesLeft.remove(0);
            if(currentNode.canSplit())
            {
                currentNode.split();
                nodesLeft.add(currentNode.getLeftNode());
                nodesLeft.add(currentNode.getRightNode());
            }
            else
            {
                leaves.add(currentNode);
            }
        }
        return leaves;
    }
    private static LinkedList<BSPMapNode> createRoomsAndGetParents(ArrayList<BSPMapNode> leaves)
    {
        LinkedList<BSPMapNode> parents = new LinkedList<BSPMapNode>();
        for(BSPMapNode leaf : leaves)
        {
            leaf.createRoom();
            if(!parents.contains(leaf.getParent()))
            {
                parents.add(leaf.getParent());
            }
        }

        return parents;
    }
    private static void connectRooms(LinkedList<BSPMapNode> parentsOfLeaves)
    {
        ArrayList<BSPMapNode> connectedParents = new ArrayList<BSPMapNode>();
        BSPMapNode currentNode;
        while(!parentsOfLeaves.isEmpty())
        {
            currentNode = parentsOfLeaves.remove();
            currentNode.connectChildren();
            connectedParents.add(currentNode);
            if(currentNode.getParent() != null &&
                    !parentsOfLeaves.contains(currentNode.getParent())&&
                    !connectedParents.contains(currentNode.getParent()))
            {
                parentsOfLeaves.add(currentNode.getParent());
            }
        }
    }

    public static void draw(Canvas canvas)
    {
        if(rootNode != null)
        {
            rootNode.draw(canvas);
        }
    }


    public static ArrayList<Monster> createMonsters(int monsterCount, int monsterStr, int monsterHP,DungeonMap map)
    {
        ArrayList<Monster> monsters = new ArrayList<Monster>();

        for(int i = 0;i<monsterCount;i++)
        {
            monsters.add(MonsterGenerator.createMonster(map.getRandomEmptyTile(),monsterStr,monsterHP));
        }
        return monsters;
    }
}
